package net.pugsplace.gpremacy.server;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.logging.Logger;

import net.pugsplace.gpremacy.packets.Chatter;
import net.pugsplace.gpremacy.packets.CurrentState;
import net.pugsplace.gpremacy.packets.GenericError;
import net.pugsplace.gpremacy.packets.LobbyInformationReq;
import net.pugsplace.gpremacy.packets.Join;
import net.pugsplace.gpremacy.packets.LobbyInformationRsp;
import net.pugsplace.gpremacy.packets.Packet;
import net.pugsplace.gpremacy.rules.RuleSet;
import net.pugsplace.gpremacy.rules.loaders.RuleLoaders;
import net.pugsplace.gpremacy.server.net.Connection;

/**
 * Acts as the lobby for all games and their players
 */
public class GameManager implements ClientListener {
	private static Logger log = Logger.getLogger(GameManager.class.getName());
	private final Collection<Connection> allConnnections;
	private final Collection<Game> allGames;
	private final Collection<RuleSet> allRules;

	public GameManager() {
		allConnnections = new ArrayList<Connection>();
		allGames = new ArrayList<Game>();
		allRules = new ArrayList<RuleSet>();
	}

	public void addClientConnection(Connection clientConn) {
		synchronized (allConnnections) {
			allConnnections.add(clientConn);
		}
		clientConn.pushListener(this);
	}

	public void clientDisconnected(Connection connectionObject) {
		synchronized (allConnnections) {
			allConnnections.remove(connectionObject);
		}
	}

	/** Create a new Game and populate it with the given rule set */
	public void createNewGame(RuleSet rules) {
		// TODO: implement
	}

	private LobbyInformationRsp getLobbyInformation() {
		LobbyInformationRsp rsp = new LobbyInformationRsp();

		return rsp;
	}

	public boolean receivedPacket(Connection connectionObject, Packet packetObject) {
		log.finest("ReceivedPacket " + connectionObject + " " + packetObject);
		if (packetObject instanceof Join) {
			String searchName = ((Join) packetObject).gameName;

			boolean found = false;
			for (Game g : allGames) {
				if (g.getName().equals(searchName)) {
					// Join this game
					g.addClientConnection(connectionObject);
					found = true;
					break;
				}
			}
			if (!found) {
				connectionObject.transmit(new GenericError("Could not join game; game not found"));
			}

			return true;
		}
		if (packetObject instanceof LobbyInformationReq) {
			connectionObject.transmit(getLobbyInformation());
			return true;
		}
		if (packetObject instanceof Chatter) {
			Chatter c = (Chatter) packetObject;
			c.sender = connectionObject.getPlayer().getName();
			c.time = Calendar.getInstance();
			sendToAllInLobby(c);

			RuleSet rs = new RuleLoaders().loadRuleset("rules/test.py");
			Packet p = new CurrentState(rs);
			sendToAllInLobby(p);

			return true;
		}
		return false;
	}

	public void sendToAllInLobby(Packet p) {
		synchronized (allConnnections) {
			for (Connection c : allConnnections) {
				if (c.isAlive() && c.peekListener() == this) {
					c.transmit(p);
				}
			}
		}
	}

}
